1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package com.sun.org.apache.xml.internal.security.signature;
22
23
24
25 import java.io.IOException;
26 import java.io.OutputStream;
27 import java.security.AccessController;
28 import java.security.PrivilegedAction;
29 import java.util.HashSet;
30 import java.util.Set;
31
32 import com.sun.org.apache.xml.internal.security.algorithms.MessageDigestAlgorithm;
33 import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException;
34 import com.sun.org.apache.xml.internal.security.c14n.InvalidCanonicalizerException;
35 import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException;
36 import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException;
37 import com.sun.org.apache.xml.internal.security.transforms.InvalidTransformException;
38 import com.sun.org.apache.xml.internal.security.transforms.Transform;
39 import com.sun.org.apache.xml.internal.security.transforms.TransformationException;
40 import com.sun.org.apache.xml.internal.security.transforms.Transforms;
41 import com.sun.org.apache.xml.internal.security.transforms.params.InclusiveNamespaces;
42 import com.sun.org.apache.xml.internal.security.utils.Base64;
43 import com.sun.org.apache.xml.internal.security.utils.Constants;
44 import com.sun.org.apache.xml.internal.security.utils.DigesterOutputStream;
45 import com.sun.org.apache.xml.internal.security.utils.IdResolver;
46 import com.sun.org.apache.xml.internal.security.utils.SignatureElementProxy;
47 import com.sun.org.apache.xml.internal.security.utils.UnsyncBufferedOutputStream;
48 import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
49 import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolver;
50 import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException;
51 import org.w3c.dom.Attr;
52 import org.w3c.dom.Document;
53 import org.w3c.dom.Element;
54 import org.w3c.dom.Node;
55 import org.w3c.dom.Text;
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104 public class Reference extends SignatureElementProxy {
105
106
107
108
109
110
111 private static boolean useC14N11 =
112 AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
113 public Boolean run() {
114 return Boolean.getBoolean
115 ("com.sun.org.apache.xml.internal.security.useC14N11");
116 }
117 });
118
119
120
121
122
123
124
125
126
127
128
129
130 public final static boolean CacheSignedNodes = false;
131
132
133 static java.util.logging.Logger log =
134 java.util.logging.Logger.getLogger(Reference.class.getName());
135
136
137 public static final String OBJECT_URI = Constants.SignatureSpecNS
138 + Constants._TAG_OBJECT;
139
140
141 public static final String MANIFEST_URI = Constants.SignatureSpecNS
142 + Constants._TAG_MANIFEST;
143
144 Manifest _manifest = null;
145 XMLSignatureInput _transformsOutput;
146
147
148 private Transforms transforms;
149
150 private Element digestMethodElem;
151
152 private Element digestValueElement;
153
154
155
156
157
158
159
160
161
162
163
164
165
166 protected Reference(Document doc, String BaseURI, String ReferenceURI, Manifest manifest, Transforms transforms, String messageDigestAlgorithm)
167 throws XMLSignatureException {
168
169 super(doc);
170
171 XMLUtils.addReturnToElement(this._constructionElement);
172
173 this._baseURI = BaseURI;
174 this._manifest = manifest;
175
176 this.setURI(ReferenceURI);
177
178
179
180
181
182
183 if (transforms != null) {
184 this.transforms=transforms;
185 this._constructionElement.appendChild(transforms.getElement());
186 XMLUtils.addReturnToElement(this._constructionElement);
187 }
188 {
189 MessageDigestAlgorithm mda =
190 MessageDigestAlgorithm.getInstance(this._doc,
191 messageDigestAlgorithm);
192
193 digestMethodElem=mda.getElement();
194 this._constructionElement.appendChild(digestMethodElem);
195 XMLUtils.addReturnToElement(this._constructionElement);
196 }
197 {
198 digestValueElement =
199 XMLUtils.createElementInSignatureSpace(this._doc,
200 Constants._TAG_DIGESTVALUE);
201
202 this._constructionElement.appendChild(digestValueElement);
203 XMLUtils.addReturnToElement(this._constructionElement);
204 }
205 }
206
207
208
209
210
211
212
213
214
215
216 protected Reference(Element element, String BaseURI, Manifest manifest)
217 throws XMLSecurityException {
218
219 super(element, BaseURI);
220 this._baseURI=BaseURI;
221 Element el=XMLUtils.getNextElement(element.getFirstChild());
222 if (Constants._TAG_TRANSFORMS.equals(el.getLocalName()) &&
223 Constants.SignatureSpecNS.equals(el.getNamespaceURI())) {
224 transforms = new Transforms(el,this._baseURI);
225 el=XMLUtils.getNextElement(el.getNextSibling());
226 }
227 digestMethodElem = el;
228 digestValueElement =XMLUtils.getNextElement(digestMethodElem.getNextSibling());;
229 this._manifest = manifest;
230 }
231
232
233
234
235
236
237
238
239
240 public MessageDigestAlgorithm getMessageDigestAlgorithm()
241 throws XMLSignatureException {
242
243 if (digestMethodElem == null) {
244 return null;
245 }
246
247 String uri = digestMethodElem.getAttributeNS(null,
248 Constants._ATT_ALGORITHM);
249
250 if (uri == null) {
251 return null;
252 }
253
254 return MessageDigestAlgorithm.getInstance(this._doc, uri);
255 }
256
257
258
259
260
261
262 public void setURI(String URI) {
263
264 if ( URI != null) {
265 this._constructionElement.setAttributeNS(null, Constants._ATT_URI,
266 URI);
267 }
268 }
269
270
271
272
273
274
275 public String getURI() {
276 return this._constructionElement.getAttributeNS(null, Constants._ATT_URI);
277 }
278
279
280
281
282
283
284 public void setId(String Id) {
285
286 if ( Id != null ) {
287 this._constructionElement.setAttributeNS(null, Constants._ATT_ID, Id);
288 IdResolver.registerElementById(this._constructionElement, Id);
289 }
290 }
291
292
293
294
295
296
297 public String getId() {
298 return this._constructionElement.getAttributeNS(null, Constants._ATT_ID);
299 }
300
301
302
303
304
305
306 public void setType(String Type) {
307
308 if (Type != null) {
309 this._constructionElement.setAttributeNS(null, Constants._ATT_TYPE,
310 Type);
311 }
312 }
313
314
315
316
317
318
319 public String getType() {
320 return this._constructionElement.getAttributeNS(null,
321 Constants._ATT_TYPE);
322 }
323
324
325
326
327
328
329
330
331
332 public boolean typeIsReferenceToObject() {
333
334 if (Reference.OBJECT_URI.equals(this.getType())) {
335 return true;
336 }
337
338 return false;
339 }
340
341
342
343
344
345
346
347
348
349 public boolean typeIsReferenceToManifest() {
350
351 if (Reference.MANIFEST_URI.equals(this.getType())) {
352 return true;
353 }
354
355 return false;
356 }
357
358
359
360
361
362
363 private void setDigestValueElement(byte[] digestValue)
364 {
365 Node n=digestValueElement.getFirstChild();
366 while (n!=null) {
367 digestValueElement.removeChild(n);
368 n = n.getNextSibling();
369 }
370
371 String base64codedValue = Base64.encode(digestValue);
372 Text t = this._doc.createTextNode(base64codedValue);
373
374 digestValueElement.appendChild(t);
375 }
376
377
378
379
380
381
382
383 public void generateDigestValue()
384 throws XMLSignatureException, ReferenceNotInitializedException {
385 this.setDigestValueElement(this.calculateDigest(false));
386 }
387
388
389
390
391
392
393
394 public XMLSignatureInput getContentsBeforeTransformation()
395 throws ReferenceNotInitializedException {
396
397 try {
398 Attr URIAttr = this._constructionElement.getAttributeNodeNS(null,
399 Constants._ATT_URI);
400 String URI;
401
402 if (URIAttr == null) {
403 URI = null;
404 } else {
405 URI = URIAttr.getNodeValue();
406 }
407
408 ResourceResolver resolver = ResourceResolver.getInstance(URIAttr,
409 this._baseURI, this._manifest._perManifestResolvers);
410
411 if (resolver == null) {
412 Object exArgs[] = { URI };
413
414 throw new ReferenceNotInitializedException(
415 "signature.Verification.Reference.NoInput", exArgs);
416 }
417
418 resolver.addProperties(this._manifest._resolverProperties);
419
420 XMLSignatureInput input = resolver.resolve(URIAttr, this._baseURI);
421
422
423 return input;
424 } catch (ResourceResolverException ex) {
425 throw new ReferenceNotInitializedException("empty", ex);
426 } catch (XMLSecurityException ex) {
427 throw new ReferenceNotInitializedException("empty", ex);
428 }
429 }
430
431
432
433
434
435
436
437
438
439 public XMLSignatureInput getTransformsInput() throws ReferenceNotInitializedException
440 {
441 XMLSignatureInput input=getContentsBeforeTransformation();
442 XMLSignatureInput result;
443 try {
444 result = new XMLSignatureInput(input.getBytes());
445 } catch (CanonicalizationException ex) {
446 throw new ReferenceNotInitializedException("empty", ex);
447 } catch (IOException ex) {
448 throw new ReferenceNotInitializedException("empty", ex);
449 }
450 result.setSourceURI(input.getSourceURI());
451 return result;
452
453 }
454
455 private XMLSignatureInput getContentsAfterTransformation(XMLSignatureInput input, OutputStream os)
456 throws XMLSignatureException {
457
458 try {
459 Transforms transforms = this.getTransforms();
460 XMLSignatureInput output = null;
461
462 if (transforms != null) {
463 output = transforms.performTransforms(input,os);
464 this._transformsOutput = output;
465
466
467 } else {
468 output = input;
469 }
470
471 return output;
472 } catch (ResourceResolverException ex) {
473 throw new XMLSignatureException("empty", ex);
474 } catch (CanonicalizationException ex) {
475 throw new XMLSignatureException("empty", ex);
476 } catch (InvalidCanonicalizerException ex) {
477 throw new XMLSignatureException("empty", ex);
478 } catch (TransformationException ex) {
479 throw new XMLSignatureException("empty", ex);
480 } catch (XMLSecurityException ex) {
481 throw new XMLSignatureException("empty", ex);
482 }
483 }
484
485
486
487
488
489
490 public XMLSignatureInput getContentsAfterTransformation()
491 throws XMLSignatureException {
492
493 XMLSignatureInput input = this.getContentsBeforeTransformation();
494
495 return this.getContentsAfterTransformation(input, null);
496 }
497
498
499
500
501
502
503
504
505 public XMLSignatureInput getNodesetBeforeFirstCanonicalization()
506 throws XMLSignatureException {
507
508 try {
509 XMLSignatureInput input = this.getContentsBeforeTransformation();
510 XMLSignatureInput output = input;
511 Transforms transforms = this.getTransforms();
512
513 if (transforms != null) {
514 doTransforms: for (int i = 0; i < transforms.getLength(); i++) {
515 Transform t = transforms.item(i);
516 String URI = t.getURI();
517
518 if (URI.equals(Transforms
519 .TRANSFORM_C14N_EXCL_OMIT_COMMENTS) || URI
520 .equals(Transforms
521 .TRANSFORM_C14N_EXCL_WITH_COMMENTS) || URI
522 .equals(Transforms
523 .TRANSFORM_C14N_OMIT_COMMENTS) || URI
524 .equals(Transforms
525 .TRANSFORM_C14N_WITH_COMMENTS)) {
526
527 break doTransforms;
528 }
529
530 output = t.performTransform(output, null);
531 }
532
533 output.setSourceURI(input.getSourceURI());
534 }
535 return output;
536 } catch (IOException ex) {
537 throw new XMLSignatureException("empty", ex);
538 } catch (ResourceResolverException ex) {
539 throw new XMLSignatureException("empty", ex);
540 } catch (CanonicalizationException ex) {
541 throw new XMLSignatureException("empty", ex);
542 } catch (InvalidCanonicalizerException ex) {
543 throw new XMLSignatureException("empty", ex);
544 } catch (TransformationException ex) {
545 throw new XMLSignatureException("empty", ex);
546 } catch (XMLSecurityException ex) {
547 throw new XMLSignatureException("empty", ex);
548 }
549 }
550
551
552
553
554
555
556 public String getHTMLRepresentation() throws XMLSignatureException {
557
558 try {
559 XMLSignatureInput nodes = this.getNodesetBeforeFirstCanonicalization();
560 Set inclusiveNamespaces = new HashSet();
561
562 {
563 Transforms transforms = this.getTransforms();
564 Transform c14nTransform = null;
565
566 if (transforms != null) {
567 doTransforms: for (int i = 0; i < transforms.getLength(); i++) {
568 Transform t = transforms.item(i);
569 String URI = t.getURI();
570
571 if (URI.equals(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS)
572 || URI.equals(
573 Transforms.TRANSFORM_C14N_EXCL_WITH_COMMENTS)) {
574 c14nTransform = t;
575
576 break doTransforms;
577 }
578 }
579 }
580
581 if (c14nTransform != null) {
582
583 if (c14nTransform
584 .length(InclusiveNamespaces
585 .ExclusiveCanonicalizationNamespace, InclusiveNamespaces
586 ._TAG_EC_INCLUSIVENAMESPACES) == 1) {
587
588
589 InclusiveNamespaces in = new InclusiveNamespaces(
590 XMLUtils.selectNode(
591 c14nTransform.getElement().getFirstChild(),
592 InclusiveNamespaces.ExclusiveCanonicalizationNamespace,
593 InclusiveNamespaces._TAG_EC_INCLUSIVENAMESPACES,0), this.getBaseURI());
594
595 inclusiveNamespaces = InclusiveNamespaces.prefixStr2Set(
596 in.getInclusiveNamespaces());
597 }
598 }
599 }
600
601 return nodes.getHTMLRepresentation(inclusiveNamespaces);
602 } catch (TransformationException ex) {
603 throw new XMLSignatureException("empty", ex);
604 } catch (InvalidTransformException ex) {
605 throw new XMLSignatureException("empty", ex);
606 } catch (XMLSecurityException ex) {
607 throw new XMLSignatureException("empty", ex);
608 }
609 }
610
611
612
613
614
615 public XMLSignatureInput getTransformsOutput() {
616 return this._transformsOutput;
617 }
618
619
620
621
622
623
624
625
626
627
628 protected XMLSignatureInput dereferenceURIandPerformTransforms(OutputStream os)
629 throws XMLSignatureException {
630
631 try {
632 XMLSignatureInput input = this.getContentsBeforeTransformation();
633 XMLSignatureInput output = this.getContentsAfterTransformation(input, os);
634
635
636
637
638
639
640 if (!Reference.CacheSignedNodes) {
641
642 this._transformsOutput = output;
643
644
645 }
646 return output;
647 } catch (XMLSecurityException ex) {
648 throw new ReferenceNotInitializedException("empty", ex);
649 }
650 }
651
652
653
654
655
656
657
658
659
660
661 public Transforms getTransforms()
662 throws XMLSignatureException, InvalidTransformException,
663 TransformationException, XMLSecurityException {
664
665 return transforms;
666 }
667
668
669
670
671
672
673
674
675 public byte[] getReferencedBytes()
676 throws ReferenceNotInitializedException, XMLSignatureException {
677 try {
678 XMLSignatureInput output=this.dereferenceURIandPerformTransforms(null);
679
680 byte[] signedBytes = output.getBytes();
681
682 return signedBytes;
683 } catch (IOException ex) {
684 throw new ReferenceNotInitializedException("empty", ex);
685 } catch (CanonicalizationException ex) {
686 throw new ReferenceNotInitializedException("empty", ex);
687 }
688
689 }
690
691
692
693
694
695
696
697
698
699
700 private byte[] calculateDigest(boolean validating)
701 throws ReferenceNotInitializedException, XMLSignatureException {
702
703 try {
704
705 MessageDigestAlgorithm mda = this.getMessageDigestAlgorithm();
706
707 mda.reset();
708 DigesterOutputStream diOs=new DigesterOutputStream(mda);
709 OutputStream os=new UnsyncBufferedOutputStream(diOs);
710 XMLSignatureInput output=this.dereferenceURIandPerformTransforms(os);
711
712
713 if (this.useC14N11 && !validating &&
714 !output.isOutputStreamSet() && !output.isOctetStream()) {
715 if (transforms == null) {
716 transforms = new Transforms(this._doc);
717 this._constructionElement.insertBefore
718 (transforms.getElement(), digestMethodElem);
719 }
720 transforms.addTransform(Transforms.TRANSFORM_C14N11_OMIT_COMMENTS);
721 output.updateOutputStream(os, true);
722 } else {
723 output.updateOutputStream(os);
724 }
725 os.flush();
726
727
728
729 return diOs.getDigestValue();
730 } catch (XMLSecurityException ex) {
731 throw new ReferenceNotInitializedException("empty", ex);
732 } catch (IOException ex) {
733 throw new ReferenceNotInitializedException("empty", ex);
734 }
735 }
736
737
738
739
740
741
742
743
744 public byte[] getDigestValue() throws Base64DecodingException, XMLSecurityException {
745 if (digestValueElement == null) {
746
747 Object[] exArgs ={ Constants._TAG_DIGESTVALUE,
748 Constants.SignatureSpecNS };
749 throw new XMLSecurityException(
750 "signature.Verification.NoSignatureElement",
751 exArgs);
752 }
753 byte[] elemDig = Base64.decode(digestValueElement);
754 return elemDig;
755 }
756
757
758
759
760
761
762
763
764
765 public boolean verify()
766 throws ReferenceNotInitializedException, XMLSecurityException {
767
768 byte[] elemDig = this.getDigestValue();
769 byte[] calcDig = this.calculateDigest(true);
770 boolean equal = MessageDigestAlgorithm.isEqual(elemDig, calcDig);
771
772 if (!equal) {
773 log.log(java.util.logging.Level.WARNING, "Verification failed for URI \"" + this.getURI() + "\"");
774 log.log(java.util.logging.Level.WARNING, "Expected Digest: " + Base64.encode(elemDig));
775 log.log(java.util.logging.Level.WARNING, "Actual Digest: " + Base64.encode(calcDig));
776 } else {
777 log.log(java.util.logging.Level.INFO, "Verification successful for URI \"" + this.getURI() + "\"");
778 }
779
780 return equal;
781 }
782
783
784
785
786
787
788 public String getBaseLocalName() {
789 return Constants._TAG_REFERENCE;
790 }
791 }